/* Gpt.c */

 #include "Gpt.h"

/* Internal structure including PIT channel configuration */
typedef struct {
  u8 callbackEnabled[GPT_CHANNEL_MAX];
  tCallbackFunction PITChannel_Callback[GPT_CHANNEL_MAX];
  u8 microTimerUsed[GPT_CHANNEL_MAX];
} PIT_ChannelStatusType;


PIT_ChannelStatusType mcal_gpt_pitChannelInternalStatus;

/**************************************************************************************
* - Function      Gpt_Init
* - Description   Initializes the GPT driver. 
* - Author        Equipo 1
* - Param         const Gpt_ConfigType* ConfigPtr 
* - Return        void
****************************************************************************************/
void Gpt_Init( const Gpt_ConfigType* ConfigPtr ){

    u8 GPTConfIndex;
    u8 PITConfIndex;
    PIT_ChannelConfigType currentPITChannelConfiguration;
    
     /* PIT counter freeze while in Freeze mode */
    PITCFLMT_PITFRZ        = 1u;
    
    
    /* Configure all GPT devices in configurations structure */
    for(GPTConfIndex = 0; GPTConfIndex < (ConfigPtr->NumerOfGptDevices); GPTConfIndex++) 
    {
      /* Configure all PIT Channels set in initialization structure */
      for(PITConfIndex=0;PITConfIndex< ConfigPtr->Gpt_DevicesConfig[GPTConfIndex].PIT_DevicesConfig->NumberOfPITChannels; PITConfIndex++) 
      { 
      
         /* Pointer to current Channel Configuration */
         currentPITChannelConfiguration =ConfigPtr->Gpt_DevicesConfig[GPTConfIndex].PIT_DevicesConfig->PIT_ChannelConfig[PITConfIndex];
          
          
            /* Enable corresponding PIT channel  */
            PITCE  |= 0x01 << currentPITChannelConfiguration.ChannelID;
		        /* Set Channel Notification/Callback configured */
            mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[currentPITChannelConfiguration.ChannelID]= currentPITChannelConfiguration.PITChannel_Callback;  
           /* 16-bit timer 0 counts with micro time base 0 */
            if(currentPITChannelConfiguration.MicroTimerSource == CNF_MICRO_TIMER_1) 
            {    
              /* Micro timer 1 selected */          
              PITMUX           |= 0x01 << currentPITChannelConfiguration.ChannelID;     
              mcal_gpt_pitChannelInternalStatus.microTimerUsed[currentPITChannelConfiguration.ChannelID] = 1;   
            } 
            else if(currentPITChannelConfiguration.MicroTimerSource == CNF_MICRO_TIMER_0) 
            {    
             /* Micro timer 0 selected */          
              PITMUX           &= ~(0x01 << currentPITChannelConfiguration.ChannelID); 
              mcal_gpt_pitChannelInternalStatus.microTimerUsed[currentPITChannelConfiguration.ChannelID] = 0;         
            }   
            
            /* Enable corresponding PIT channel interrupt */
            PITINTE |= 0x01 << currentPITChannelConfiguration.ChannelID; 
            /* Clear corresponding PIT channel interrupt Flag */
            PITTF   |= 0x01 << currentPITChannelConfiguration.ChannelID;
            
            /* Corresponding PIT channel time in microsecons - 16-bit Timer value */
            switch(currentPITChannelConfiguration.ChannelID) {
              case GPT_CHANNEL_0: 
                   PITLD0     = currentPITChannelConfiguration.TimeInUs;
                   break;
              case GPT_CHANNEL_1:
                   PITLD1     = currentPITChannelConfiguration.TimeInUs;
                   break;
              case GPT_CHANNEL_2:
                   PITLD2     = currentPITChannelConfiguration.TimeInUs;
                   break;
              case GPT_CHANNEL_3:
                   PITLD3     = currentPITChannelConfiguration.TimeInUs;
                   break;                                                         
            }
   
        }
            /* Precalculated PIT microtimer 0 (8-bit time base divider)*/
            PITMTLD0   = ConfigPtr->Gpt_DevicesConfig[GPTConfIndex].PIT_DevicesConfig->MicroTimerConfig0;
            /* Precalculated PIT microtimer 1  (8-bit time base divider)*/
            PITMTLD1   = ConfigPtr->Gpt_DevicesConfig[GPTConfIndex].PIT_DevicesConfig->MicroTimerConfig1;            
            /* Precalculated PIT count down value */
           
       
    }                                               

 
  
}

/**************************************************************************************
* - Function      Gpt_StartTimer
* - Description   Starts a timer channel.
* - Author        Equipo 1
* - Params        Gpt_ChannelType Channel, Gpt_ValueType Value
* - Return        void
****************************************************************************************/
void Gpt_StartTimer( Gpt_ChannelType Channel )
{
 
 /* Validate Channel number */   
 if (Channel < GPT_CHANNEL_MAX) {

    /* Load 8-bit microtimer load register  into the 8-bit micro timer down-counter  */
    
    if( mcal_gpt_pitChannelInternalStatus.microTimerUsed[Channel] == CNF_MICRO_TIMER_0){
      
      PITCFLMT_PFLMT0     = 1u;
    } 
    else if( mcal_gpt_pitChannelInternalStatus.microTimerUsed[Channel] == CNF_MICRO_TIMER_1){
      
      PITCFLMT_PFLMT1     = 1u;
    }    
        
    /* Load corresponding 16-bit timer load register into the 16-bit timer down-counter */
    PITFLT   = 0x01 << Channel;
    /* Enable Periodic Interrup Timer */
    PITCFLMT_PITE       = 1u;

  }
}


/**************************************************************************************
* - Function      Gpt_StopTimer
* - Description   Stops a timer channel. 
* - Author        Equipo 1
* - Param         Gpt_ChannelType Channel
* - Return        void
****************************************************************************************/
void Gpt_StopTimer( Gpt_ChannelType Channel ){

  /* Validate Channel number */
  if (Channel < GPT_CHANNEL_MAX) {
  
    /* Disable corresponding Channel */
    PITCE &= ~(0x01 << Channel); 
   
   	/* Disable Periodic Interrup Timer, thus halting time basis of scheduler */
   // PITCFLMT_PITE       = 0u; 
  }
    
}


/**************************************************************************************
* - Function      Gpt_EnableNotification
* - Description   Enables the interrupt notification for a channel (relevant in normal mode). 
* - Author        Equipo 1
* - Param         Gpt_ChannelType Channel 
* - Return        void
****************************************************************************************/
void Gpt_EnableNotification( Gpt_ChannelType Channel ){


  /* Validate Channel number */  
  if (Channel < GPT_CHANNEL_MAX) {
  
       /* Update internal structure to enable notifications */
       mcal_gpt_pitChannelInternalStatus.callbackEnabled[Channel] = CNF_NOTIFICATION_ENABLED;
  }
  
}


/**************************************************************************************
* - Function      Gpt_DisableNotification
* - Description   Disables the interrupt notification for a channel (relevant in normal mode). 
* - Author        Equipo 1
* - Param         Gpt_ChannelType Channe
* - Return        void
****************************************************************************************/
void Gpt_DisableNotification( Gpt_ChannelType Channel ){

  /* Validate Channel number */
  if (Channel < GPT_CHANNEL_MAX) {

	/* Update internal structure to disable notifications */
     mcal_gpt_pitChannelInternalStatus.callbackEnabled[Channel] = CNF_NOTIFICATION_DISABLED;
  }  
  
}





/**************************************************************************************
* - Function      vfnPIT_Channel0_Isr, vfnPIT_Channel1_Isr, vfnPIT_Channel2_Isr, vfnPIT_Channel3_Isr
* - Description   PTI channels 0,1,2 and 3 Interrupt service routines
* - Author        Equipo 1
* - Param         void
* - Return        void
****************************************************************************************/

#pragma CODE_SEG __NEAR_SEG NON_BANKED

void interrupt  vfnPIT_Channel0_Isr( void  )
{
    /* Verify that Real Time Interrupt caused the interrupt */
    if( PITTF_PTF0 == 1u )
    {
         /* call callback function, if initialized and Notification is enabled */
        if(   mcal_gpt_pitChannelInternalStatus.callbackEnabled[0] == CNF_NOTIFICATION_ENABLED && mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[0] != 0x00 )
        {
           mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[0]();
        }
    }
    /* Clear the real time interrupt flag */
    PITTF_PTF0 = 1u;
}


void interrupt  vfnPIT_Channel1_Isr( void  )
{
    /* Verify that Real Time Interrupt caused the interrupt */
    if( PITTF_PTF1 == 1u )
    {
       /* call callback function, if initialized and Notifications enabled */
        if(   mcal_gpt_pitChannelInternalStatus.callbackEnabled[1] == CNF_NOTIFICATION_ENABLED && mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[1] != 0x00 )
        {
           mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[1]();
        }
    }
    /* Clear the real time interrupt flag */
    PITTF_PTF1 = 1u;
}

void interrupt  vfnPIT_Channel2_Isr( void  )
{
    /* Verify that Real Time Interrupt caused the interrupt */
    if( PITTF_PTF2 == 1u )
    {
         /* call callback function, if initialized and Notification enabled */
        if(   mcal_gpt_pitChannelInternalStatus.callbackEnabled[2] == CNF_NOTIFICATION_ENABLED && mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[2] != 0x00 )
        {
           mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[2]();
        }
    }
    /* Clear the real time interrupt flag */
    PITTF_PTF2 = 1u;
}

void interrupt  vfnPIT_Channel3_Isr( void  )
{
    /* Verify that Real Time Interrupt caused the interrupt */
    if( PITTF_PTF3 == 1u )
    {
        /* call callback function, if initialized and Notification enabled */
        if(   mcal_gpt_pitChannelInternalStatus.callbackEnabled[3] == CNF_NOTIFICATION_ENABLED && mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[3] != 0x00 )
        {
           mcal_gpt_pitChannelInternalStatus.PITChannel_Callback[3]();
        }
    }
    /* Clear the real time interrupt flag */
    PITTF_PTF3 = 1u;
}
#pragma CODE_SEG DEFAULT